#include <iostream>
#include <vector>
#include <string>
#include <functional>
#include <unistd.h>
#include <pthread.h>

using namespace std;

// 定义一个条件变量
pthread_cond_t cond;
// 定义一个互斥锁
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

vector<function<void()>> funcs;

void show()
{
    cout << "hello show" << endl;
}

void print()
{
    cout << "hello print" << endl;
}

// 定义全局退出变量
volatile bool quit = false;

void *waitCommand(void *args)
{
    pthread_detach(pthread_self());
    while(!quit)
    {
        // 执行了下面的代码，就证明了某一种条件不就绪，要线程等待
        // 让对应的线程进行等待，等待被唤醒
        // 三个线程，都会在条件变量下进行排队
        pthread_cond_wait(&cond, &mutex);
        for(auto &f : funcs)
        {
            f(); 
        }
    }

    cout << "thread id: " << pthread_self() << " end..." << endl;

    return nullptr;
}

int main()
{
    funcs.push_back(show);
    funcs.push_back(print);
    funcs.push_back([](){
        cout << "hello world!" << endl;
    });

    pthread_cond_init(&cond, nullptr);
    pthread_t t1, t2, t3;
    pthread_create(&t1, nullptr, waitCommand, nullptr);
    pthread_create(&t2, nullptr, waitCommand, nullptr);
    pthread_create(&t3, nullptr, waitCommand, nullptr);

    while(true)
    {
        char n = 'a';
        cout << "请输入你的command(n/q): ";
        cin >> n;
        if(n == 'n')
        {
            pthread_cond_signal(&cond);
        }
        else
        {
            break;
        }
        sleep(1);
    }

    cout << "main thread quit" << endl; 
    
    pthread_cond_destroy(&cond);

    return 0;
}

// pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

// int cnt = 100;

// void *startRoutine(void *args)
// {
//     string name = static_cast<char *>(args);
//     while(true)
//     {
//         pthread_mutex_lock(&mutex);
//         pthread_mutex_lock(&mutex);
//         cout << name << "count : " << cnt-- << endl;
//         pthread_mutex_unlock(&mutex);
//         sleep(1);
//     }
// }

// int main()
// {
//     pthread_t t1;
//     pthread_create(&t1, nullptr, startRoutine, (void*)"thread 1");
//     pthread_t t2;
//     pthread_create(&t2, nullptr, startRoutine, (void*)"thread 2");
    
//     pthread_join(t1, nullptr);
//     pthread_join(t2, nullptr);


//     return 0;
// }